#include "gameobjectstreewidget.h"
#include "document.h"
#include "application.h"
#include "gameObjects/abstractgameobject.h"
#include "modes/objecteditormode.h"
#include "utils.h"

GameObjectsTreeWidget::GameObjectsTreeWidget(QWidget *parent) :
    QTreeWidget(parent)
{
	connect(this, &QTreeWidget::itemSelectionChanged, 
		this, &GameObjectsTreeWidget::onItemSelectionChanged);
}

void GameObjectsTreeWidget::onDocumentChanged( QPointer<Document> document )
{
	if(!document)
	{
		clear();
	}
	else
	{
		// create connections
		connect(document, &Document::gameObjectAdded, 
			this, &GameObjectsTreeWidget::onGameObjectAdded);

		connect(document, &Document::gameObjectRemoved, 
			this, &GameObjectsTreeWidget::onGameObjectRemoved);

		connect(document, &Document::objectDataChanged, 
			this, &GameObjectsTreeWidget::onObjectDataChanged);
	}
}

void GameObjectsTreeWidget::onGameObjectAdded( QPointer<AbstractGameObject> go )
{
	GameObjectsTreeWidgetItem* pNewItem = new GameObjectsTreeWidgetItem;
	pNewItem->object = go;
	pNewItem->setText(0, go->name());

	if(go->type() == GOT_Actor)
	{
		addTopLevelItem(pNewItem);
	}
	else //if(go->type() == GOT_VisualObject)
	{
		QPointer<AbstractGameObject> parentActor = go->parentGameObject();
		GameObjectsTreeWidgetItem* pParentItem = 
			treeWidgetItemFromObject<GameObjectsTreeWidgetItem, AbstractGameObject>(parentActor, this);
		Q_ASSERT(pParentItem);
		pParentItem->addChild(pNewItem);
		pParentItem->setExpanded(true);
	}

	// NOTE: blocking so we dont want to broadcast null selected object
	blockSignals(true);
	clearSelection();
	blockSignals(false);

	pNewItem->setSelected(true);
}

void GameObjectsTreeWidget::onGameObjectRemoved( QPointer<AbstractGameObject> go )
{
	if(go->type() == GOT_Actor)
	{
		int index = 
			indexOfTopLevelItem(treeWidgetItemFromObject<GameObjectsTreeWidgetItem, AbstractGameObject>(go, this));
		QTreeWidgetItem* pItem = takeTopLevelItem(index);
		delete pItem;
	}
	else if(go->type() == GOT_VisualObject)
	{
		QPointer<AbstractGameObject> parentActor = go->parentGameObject();
		GameObjectsTreeWidgetItem* pParentItem = 
			treeWidgetItemFromObject<GameObjectsTreeWidgetItem, AbstractGameObject>(parentActor, this);
		Q_ASSERT(pParentItem);

		GameObjectsTreeWidgetItem* pVisualObjectItem = 
			treeWidgetItemFromObject<GameObjectsTreeWidgetItem, AbstractGameObject>(go, this);
		Q_ASSERT(pVisualObjectItem);
		pParentItem->removeChild(pVisualObjectItem);
		delete pVisualObjectItem;
	}
}

void GameObjectsTreeWidget::onItemSelectionChanged()
{
	QList<QTreeWidgetItem*> selItems = selectedItems();
	Q_ASSERT(selItems.size() < 2);

	QPointer<AbstractGameObject> result;
	
	if(selItems.size())
	{
		result = objectFromTreeWidgetItem<GameObjectsTreeWidgetItem, AbstractGameObject>(selItems.first());
	}

	emit selectedObjectChanged(result);
}

void GameObjectsTreeWidget::onObjectDataChanged( QPointer<AbstractGameObject> go )
{
	GameObjectsTreeWidgetItem* pVisualObjectItem = 
		treeWidgetItemFromObject<GameObjectsTreeWidgetItem, AbstractGameObject>(go, this);
	pVisualObjectItem->setText(0, go->name());
}

void GameObjectsTreeWidget::setObjectEditorMode( QPointer<Modes::EditorMode> oem )
{
	connect(oem, &Modes::ObjectEditorMode::documentChanged, 
		this, &GameObjectsTreeWidget::onDocumentChanged);

	QPointer<Modes::ObjectEditorMode> pOEM = qobject_cast<Modes::ObjectEditorMode*>(oem);
	Q_ASSERT(pOEM);
	connect(this, &GameObjectsTreeWidget::selectedObjectChanged, 
		pOEM, &Modes::ObjectEditorMode::onSelectedObjectChanged);
}
